/*
 * OpenParts
 * A dynamic-loading components framework for GWT
 * Copyright (C) 2011 Christophe Bouthier  [chris{AT}binary-gastronome{DOT}fr]
 *
 * This work is partially based on work I have done at INRIA (http://www.inria.fr) 
 * in the context of the Qualipso European Project (http://qualipso.org/),
 * The work done at INRIA is Copyright (C) 2006-2011 INRIA
 *
 * This work is distributed under the LGPL version 3
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation. See the GNU
 * Lesser General Public License in LGPL.txt for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package fr.openparts.OpenParts.test.gwt.tests;

import com.google.gwt.junit.client.GWTTestCase;

import fr.openparts.OpenParts.client.OPBindingResource;
import fr.openparts.OpenParts.client.OPBindingService;

/**
 * GWT tests for OPBindingService.
 * 
 * @author Christophe Bouthier [chris{AT}binary-gastronome{DOT}fr]
 * @creation.date 31 December 2009
 */
public class OPBindingServiceTestGwt extends GWTTestCase {

    private static final String SERVICE_NAME = "dummyService";
    private static final String RESOURCE_NAME = "dummyResource";

    private OPBindingService service;
    private OPBindingResource resource;

    /**
     * Return the name of the tested GWT Module.
     * 
     * @see com.google.gwt.junit.client.GWTTestCase#getModuleName()
     */
    @Override
    public final String getModuleName() {
        return "fr.openparts.OpenParts.test.gwt.TestOpenParts";
    }

    /**
     * Called at the start of each test to set up the service.
     * 
     * @see com.google.gwt.junit.client.GWTTestCase#gwtSetUp()
     */
    @Override
    protected void gwtSetUp() throws Exception {
        super.gwtSetUp();
        service = OPBindingService.serviceFactory(SERVICE_NAME);
        resource = OPBindingResource.resourceFactory(RESOURCE_NAME);
    }

    /**
     * Test creating an OPBindingService. Should get something not null.
     */
    public final void testCreatingOPBindingService() {
        assertNotNull("Binding service shouldn't be null", service);
    }

    /**
     * Test creating an OPBindingService with a null service name. Should raise an assertion error.
     */
    public final void testCreatingOPBindingServiceWithNullServiceName() {
        if (assertionsAreEnabled()) {
            try {
                OPBindingService.serviceFactory(null);
                fail("OPBindingService should raise an assertion error when creating a service with null service name.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError e", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test getting the service name. Should get SERVICE_NAME.
     */
    public final void testGettingServiceName() {
        final String serviceName = service.getServiceName();
        assertNotNull(" Service name shouldn't be null", serviceName);
        assertEquals("Service name should be dummyService", SERVICE_NAME, serviceName);
    }

    /**
     * Test getting all names of binded resources. Should get the corresponding array. 
     */
    public final void testGettingResourcesNames() {
        service.bindResource(resource);
        final OPBindingResource resource2 = OPBindingResource.resourceFactory(RESOURCE_NAME + "2");
        service.bindResource(resource2);
        final String[] resourcesNames = service.getResourcesNames();
        assertNotNull("Names array shouldn't be null", resourcesNames);
        assertEquals("Names array should contains only 2 elements", 2, resourcesNames.length);
        boolean resourceName1Found = false;
        boolean resourceName2Found = false;
        for (String resourceName : resourcesNames) {
            if (resourceName.equals(RESOURCE_NAME)) {
                resourceName1Found = true;
            } else if (resourceName.equals(RESOURCE_NAME + "2")) {
                resourceName2Found = true;
            } else {
                fail("Names array contains an unknown resource name: " + resourceName);
            }
        }
        assertTrue("resource name 1 should have been found", resourceName1Found);
        assertTrue("resource name 2 should have been found", resourceName2Found);
    }
    
    /**
     * Test getting all names of binded resources without resources binded. Should get an empty but not null array.
     */
    public final void testGettingResourcesNamesWithoutResources() {
        final String[] resourcesNames = service.getResourcesNames();
        assertNotNull("Names array shouldn't be null", resourcesNames);
        assertEquals("Names array should be empty", 0, resourcesNames.length);
    }
    
    /**
     * Test binding a resource. Shouldn't get an exception.
     */
    public final void testBindingResource() {
        service.bindResource(resource);
        assertNotNull(service.getResource(RESOURCE_NAME));
    }

    /**
     * Test binding a null resource. Should raise an assertion error.
     */
    public final void testBindingNullResource() {
        if (assertionsAreEnabled()) {
            try {
                service.bindResource(null);
                fail("OPBindingService should raise an assertionError when binding a null resource.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test binding an already binded resource. Shouldn't get an exception.
     */
    public final void testBindingAlreadyBindedResource() {
        service.bindResource(resource);
        final OPBindingResource resource2 = OPBindingResource.resourceFactory(RESOURCE_NAME);
        assertNotSame("resources shouldn't be the same", resource, resource2);
        service.bindResource(resource2);
        assertEquals("Should return the lastest binded resource", resource2, service.getResource(RESOURCE_NAME));
    }

    /**
     * Test getting a binding resource. Should get the binded resource.
     */
    public final void testGettingBindedResource() {
        service.bindResource(resource);
        final OPBindingResource r = service.getResource(RESOURCE_NAME);
        assertNotNull("resource shouldn't be null", r);
        assertEquals("Should return the binded resource", resource, r);
        ;
    }

    /**
     * Test getting a binded resource without binding the resource first. Should get null.
     */
    public final void testGettingResourceWithoutBindingFirst() {
        assertNull("resource should be null if not binded first", service.getResource(RESOURCE_NAME));
    }

    /**
     * Test getting a binded resource by passing null as name. Should raise an assertion error.
     */
    public final void testGettingNullResource() {
        if (assertionsAreEnabled()) {
            service.bindResource(resource);
            try {
                service.getResource(null);
                fail("OPBindingService should raise an assertion error when getting a resource by passing a null name.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test getting an inexistent resource. Should get null.
     */
    public final void testGettingInexistentResource() {
        service.bindResource(resource);
        assertNull("resource should be null if inexistant name is given", service.getResource("INEXISTENT_RESOURCE"));
    }

    /**
     * Check if assertions are enabled.
     * 
     * @return true if assertions are enabled, false otherwise
     */
    private final boolean assertionsAreEnabled() {
        try {
            assert false;
            return false;
        } catch (AssertionError e) {
            return true;
        }
    }

}
